﻿// Колесов 
using System;
using ComLaoBase;
using System.Collections.Generic;
using Transfer.Tools;

namespace Transfer
{
    /// <summary> Класс обеспечивает доступ к параметрам номенклатуры.
    /// </summary>
    public class LaoNom
    {
        LAOBase _laoNom;
        LAOBase _laoNomTax;
        LAOBase _laoEi;
        LAOBase _laoNomEi;

        public LaoNom()
        {
            _laoNom = LAO_DB.Open("TNomObj", "Index_1");    // Cd
            _laoNomTax = _laoNom.GetSubObject("TNomTaxObj");
            _laoNomEi = _laoNom.GetSubObject("TNomEiObj");
            _laoEi = LAO_DB.Open("TEiObj", "Index_3");      // EiSh - шифр ЕИ

        }

        public void Close()
        {
            _laoNomTax.Close();
            _laoNomEi.Close();
            _laoNom.Close();
            _laoEi.Close();
        }

        /// <summary> Получение Rcd номеклатуры по артикулу
        /// </summary>
        /// <param name="code">Артикул</param>
        /// <returns>Rcd</returns>
        public Int32 GetRcdByCode(string code)
        {
            Int32 rcd = 0;
            _laoNom.Sort("Index_1");    // Cd
            if (_laoNom.Find(1, code.Trim(), 0, 0, 0, 0, 0, 0, 0, 0, 0))
                rcd = _laoNom.GetInteger("Rcd");
            return rcd;
        }

        /// <summary> Получение Rcd единицы измерений по шифру
        /// </summary>
        /// <param name="code">Шифр ЕИ</param>
        /// <returns>Rcd</returns>
        public Int32 GetEiRcdByCode(string code)
        {
            Int32 rcd = 0;
            _laoEi.Sort("Index_3");    // EiSh
            if (_laoEi.Find(1, code.Trim(), 0, 0, 0, 0, 0, 0, 0, 0, 0))
                rcd = _laoEi.GetInteger("Rcd");
            return rcd;
        }

        /// <summary> Получение шифра единицы измерений по Rcd
        /// </summary>
        /// <param name="code">Rcd ЕИ</param>
        /// <returns>Rcd</returns>
        public string GetEiShByCode(int rcd)
        {
            string sh = string.Empty;
            _laoEi.Sort("Index_2");    // Rcd
            if (_laoEi.Find(1, rcd, 0, 0, 0, 0, 0, 0, 0, 0, 0))
                sh = _laoEi.GetString("ShNm").Trim();
            return sh;
        }

        /// <summary> Метод возвращает набор параметров номенклатуры
        /// </summary>
        /// <param name="code">Артикул или штрихкод</param>
        /// <param name="code">Признак штрихкода - true</param>
        /// <returns></returns>
        public NomPrm GetNomPrm(string code, bool isBarCode)
        {
            NomPrm nomPrm = new NomPrm();
            nomPrm.Art = (isBarCode) ? GetArtByBar(code) : code.Trim();
            _laoNom.Sort("Index_1");    // Cd
            if (!_laoNom.Find(1, nomPrm.Art, 0, 0, 0, 0, 0, 0, 0, 0, 0))
                return nomPrm;

            nomPrm.Rcd = _laoNom.GetInteger("Rcd");
            // Читаем параметры НДС из первой записи.
            // Предполагаем, что других налогов у номенклатуры нет.
            _laoNomTax.First();
            if (!_laoNomTax.IsEOO())
            {
                nomPrm.TaxCd = _laoNomTax.GetInteger("Cd");
                nomPrm.TaxRateCd = _laoNomTax.GetInteger("CdRate");
            }

            // Заполним список параметров единиц измерения номенклатуры.
            _laoNomEi.First();
            while(!_laoNomEi.IsEOO())
            {
                NomEiPrm nmei = new NomEiPrm();
                nmei.OsnEi = (_laoNomEi.GetInteger("Osn") != 0);    // Признак основной единицы
                nmei.RcdEi = _laoNomEi.GetInteger("Cd");            // Rcd в справочнике
                nmei.KoefOsn = Helper.StrToDecimal(_laoNomEi.GetString("QtOsn").Trim());  // Коэффициент
                nmei.ShNm = GetEiShByCode(nmei.RcdEi);              // Шифр ЕИ в справочнике
                nmei.QtBrut = Helper.StrToDecimal(_laoNomEi.GetString("QtBrut")); // Вес брутто основной ЕИ
                nmei.QtNett = Helper.StrToDecimal(_laoNomEi.GetString("QtNett")); // Вес нетто основной ЕИ
                // В ИС-ПРО точность задается количеством знаков после запятой + 1. 
                // Ноль - если точность не указана.
                nmei.Precision = _laoNomEi.GetInteger("Acc");       // Точность ЕИ
                if (nmei.Precision > 0) nmei.Precision -= 1;        // Приводим точность к нормальному значению 

                nomPrm.EiList.Add(nmei);

                if (nmei.OsnEi) // Для основной ЕИ сохраним ее Rcd и Веса
                {
                    nomPrm.RcdOsnEi = nmei.RcdEi;
                    nomPrm.QtBrut = nmei.QtBrut;
                    nomPrm.QtNett = nmei.QtNett;
                }

                _laoNomEi.Next();
            }

            return nomPrm;
        }

        /// <summary> Пересчет количества из заданной единицы измерения в основную
        /// </summary>
        /// <param name="rcdEI"></param>
        /// <param name="qt"></param>
        /// <returns></returns>
        public static decimal CalculateToOsn(NomPrm nomPrm, int rcdEI, decimal qt)
        {
            decimal qtOsn = 0;

            // Найдем заданную ЕИ в списке
            foreach (NomEiPrm neip in nomPrm.EiList)
            {
                if (neip.RcdEi == rcdEI)     // Нашли указанную ЕИ
                {
                    if (neip.OsnEi)          // Указанная ЕИ - основная, пересчет не нужен
                    {
                        qtOsn = qt;
                    }
                    else
                    {
                        qtOsn = qt * neip.KoefOsn;
                    }
                    break;
                }
            }

            return qtOsn;
        }

        /// <summary> Пересчет цены из одной ЕИ в другую
        /// </summary>
        /// <param name="nomprm">Параметры номенклатуры</param>
        /// <param name="rcdEiFrom">Rcd ЕИ, в которой указана цена</param>
        /// <param name="rcdEiTo">Rcd ЕИ, в которую пересчитываем цену</param>
        /// <param name="cena">Цена, из которой считаем</param>
        /// <returns>Посчитанная цена</returns>
        public static decimal ReCalcPriceEi(NomPrm nomPrm, int rcdEiFrom, int rcdEiTo, decimal cena)
        {
            decimal cnOut = 0;
            
            if (rcdEiFrom == rcdEiTo)       // Пересчет не требуется
                return cena;

            // Пересчет ведем через основную единицу.
            decimal KoefFrom = 0;   // Коэффициент для исходной единицы
            decimal KoefTo = 0;     // Коэффициент для выходной единицы

            // Найдем заданные ЕИ и основную ЕИ в списке
            foreach (NomEiPrm neip in nomPrm.EiList)
            {
                if (neip.RcdEi == rcdEiFrom)     
                    KoefFrom = neip.KoefOsn;
                if (neip.RcdEi == rcdEiTo)     
                    KoefTo = neip.KoefOsn;

            }

            if(KoefFrom != 0 )
                cnOut = cena * KoefTo / KoefFrom;

            return cnOut;
        }

        /// <summary> Расчет веса брутто и нетто для заданного количества в заданной ЕИ
        /// Сразу в строковом формате ИС-ПРО.
        /// </summary>
        /// <param name="nomPrm">Параметры номенклатуры</param>
        /// <param name="rcdEI">Rcd единицы измерения</param>
        /// <param name="qt">Количество</param>
        /// <param name="brut">результат - вес брутто строкой</param>
        /// <param name="nett">результат - вес нетто строкой</param>
        public static void CalcBrutNett(NomPrm nomPrm, int rcdEI, decimal qt, out string brut, out string nett)
        {
            brut = string.Empty;
            nett = string.Empty;
            // Найдем заданную ЕИ в списке
            foreach (NomEiPrm neip in nomPrm.EiList)
            {
                if (neip.RcdEi == rcdEI)     // Нашли указанную ЕИ
                {
                    brut = Math.Round(qt * neip.QtBrut, 3, MidpointRounding.AwayFromZero).ToString().Replace(',', '.');
                    nett = Math.Round(qt * neip.QtNett, 3, MidpointRounding.AwayFromZero).ToString().Replace(',', '.');
                    break;
                }
            }
            return;
        }

        /// <summary> Поиск в ИС-ПРО артикула номенклатуры по ее штрихкоду.
        /// Индекса нет, поэтому ищем тупо перебором.
        /// </summary>
        /// <param name="barcode">Штрихкод</param>
        /// <returns>Артикул</returns>
        public string GetArtByBar(string barcode)
        {
            barcode = barcode.Trim();
            _laoNom.First();
            while (!_laoNom.IsEOO())
            {
                string tmpcode = _laoNom.GetString("BarCd", "").Trim();
                if (tmpcode == barcode)
                    return _laoNom.GetString("Cd", "").Trim();
                _laoNom.Next();
            }
            return "";
        }
    }

    /// <summary> Набор параметров номенклатуры
    /// </summary>
    public class NomPrm
    {
        /// <summary> Артикул
        /// </summary>
        public string Art = string.Empty;

        /// <summary> Rcd номенклатуры
        /// </summary>
        public Int32 Rcd = 0;

        /// <summary> Код налога (НДС)
        /// </summary>
        public Int32 TaxCd = 0;

        /// <summary> Код ставки налога
        /// </summary>
        public Int32 TaxRateCd = 0;

        ///// <summary> Ставка налога
        ///// </summary>
        //public Int32 TaxRateValue = 0;

        /// <summary> Список параметров единиц измерения номенклатуры
        /// </summary>
        public List<NomEiPrm> EiList = new List<NomEiPrm>();

        /// <summary> Rcd основной единицы измерения
        /// </summary>
        public int RcdOsnEi = 0;

        /// <summary> Вес брутто основной ЕИ 
        /// </summary>
        public decimal QtBrut = 0;

        /// <summary> Вес нетто основной ЕИ
        /// </summary>
        public decimal QtNett = 0;

    }
    
    /// <summary> Параметры одной единицы измерения номенклатуры
    /// </summary>
    public class NomEiPrm
    {
        /// <summary> Признак основной единицы измерения
        /// </summary>
        public bool OsnEi
        {
            get { return _osnEi; }
            set { _osnEi = value; }
        }
        private bool _osnEi = false;

        /// <summary> Шифр единицы измерения
        /// </summary>
        public string ShNm
        {
            get { return _shNm; }
            set { _shNm = value; }
        }
        private string _shNm = string.Empty;

        /// <summary> Rcd единицы измерения в справочнике
        /// </summary>
        public int RcdEi
        {
            get { return _rcdEi; }
            set { _rcdEi = value; }
        }
        private int _rcdEi = 0;

        /// <summary> Коэффициент пересчета в основную единицу измерения
        /// </summary>
        public decimal KoefOsn
        {
            get { return _koefOsn; }
            set { _koefOsn = value; }
        }
        private decimal _koefOsn = 0;

        /// <summary> Вес брутто
        /// </summary>
        public decimal QtBrut
        {
            get { return _qtBrut; }
            set { _qtBrut = value; }
        }
        private decimal _qtBrut = 0;

        /// <summary> Вес нетто
        /// </summary>
        public decimal QtNett
        {
            get { return _qtNett; }
            set { _qtNett = value; }
        }
        private decimal _qtNett = 0;

        /// <summary> Точность единицы измерения (количество знаков после точки)
        /// </summary>
        public int Precision
        {
            get { return _precision; }
            set { _precision = value; }
        }
        private int _precision = 0;
    }
}
